package cn.feng.thinkInJava.b3_1_多线程并发.concurrency.a21_04_02;

//: concurrency/Interrupting.java
// Interrupting a blocked thread.
import java.util.concurrent.*;
import java.io.*;
import static net.mindview.util.Print.*;

class SleepBlocked implements Runnable
{
	public void run()
	{
		try
		{
			TimeUnit.SECONDS.sleep(100);
		}
		catch(InterruptedException e)
		{
			print("InterruptedException");
		}
		print("Exiting SleepBlocked.run()");
	}
}

class IOBlocked implements Runnable
{
	private InputStream in;
	
	public IOBlocked(InputStream is)
	{
		in=is;
	}
	
	public void run()
	{
		try
		{
			print("Waiting for read():");
			in.read();
		}
		catch(IOException e)
		{
			if(Thread.currentThread().isInterrupted())
			{
				print("Interrupted from blocked I/O");
			}
			else
			{
				throw new RuntimeException(e);
			}
		}
		print("Exiting IOBlocked.run()");
	}
}

class SynchronizedBlocked implements Runnable
{
	public synchronized void f()
	{
		while(true) // Never releases lock
			Thread.yield();
	}
	
	public SynchronizedBlocked()
	{
		new Thread()
		{
			public void run()
			{
				f(); // Lock acquired by this thread
			}
		}.start();
	}
	
	public void run()
	{
		print("Trying to call f()");
		f();
		print("Exiting SynchronizedBlocked.run()");
	}
}

public class Interrupting
{
	private static ExecutorService exec=Executors.newCachedThreadPool();
	
	static void test(Runnable r) throws InterruptedException
	{
		Future<?> f=exec.submit(r);
		TimeUnit.MILLISECONDS.sleep(100);
		print("Interrupting "+r.getClass().getName());
		f.cancel(true); // Interrupts if running
		print("Interrupt sent to "+r.getClass().getName());
	}
	
	/**
	 * 每个任务都表示一种不同类型的阻塞,SleepBlocked是可中断的阻塞示例,而IOBlocked和SynchronizedBlocked是不可中断
	 * 阻塞示例,这个程序证明I/O和在synchronized块上的等待是不可中断的,但是通过代码预览,可以预见到这一点------无论是是I/O
	 * 和在synchronized方法,都不需要在InterruptException处理器
	 * 
	 * 前两个类很简单直观:在第一个类run()方法中调用了sleep()方法,而在第二个类中调用了read().但是为了演示SynchronizedBlocked,我们
	 * 必须首先获取锁.这是通过在构造器中创建匿名的Thread类来实现的,这个匿名的Thread类型的对象通过调用f()获取了对象锁(这个线程必须有别于
	 * SynchronizedBlocked驱动的run()的线程,因为一个线程可以多次获得某个对象锁),由于f()永远都不返回,一次这个锁永远不会释放,而SynchronizedBlocked.run()
	 * 在试图调用f(),并阻塞以等待这个锁释放.
	 * 从输出中可以看到,你能够中断对sleep()的调用(或者任何要求抛出InterruptException的调用),但是你不能中断正在试图获取synchronized锁
	 * 或者试图执行I/O操作的线程,这有点烦恼,特别是在创建执行I/O的任务时,因为这意味着I/O具有锁住你多线程程序的潜在可能.特别是基于Web的程序,则更是关乎利害
	 * 
	 */
	public static void main(String[] args) throws Exception
	{
		test(new SleepBlocked());
		test(new IOBlocked(System.in));
		test(new SynchronizedBlocked());
		TimeUnit.SECONDS.sleep(3);
		print("Aborting with System.exit(0)");
		System.exit(0); // ... since last 2 interrupts failed
	}
} /* Output: (95% match)
Interrupting SleepBlocked
InterruptedException
Exiting SleepBlocked.run()
Interrupt sent to SleepBlocked
Waiting for read():
Interrupting IOBlocked
Interrupt sent to IOBlocked
Trying to call f()
Interrupting SynchronizedBlocked
Interrupt sent to SynchronizedBlocked
Aborting with System.exit(0)
*///:~
